package cn.iocoder.yudao.module.energy.controller.admin.report;

import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.energy.controller.admin.report.vo.EnergyReportDataBatchImportVO;
import cn.iocoder.yudao.module.energy.controller.admin.report.vo.EnergyReportDataCreateReqVO;
import cn.iocoder.yudao.module.energy.controller.admin.report.vo.EnergyReportDataPageReqVO;
import cn.iocoder.yudao.module.energy.controller.admin.report.vo.EnergyReportDataRespVO;
import cn.iocoder.yudao.module.energy.controller.admin.report.vo.EnergyReportDataUpdateReqVO;
import cn.iocoder.yudao.module.energy.controller.admin.report.vo.EnergyReportDataExportVO;
import cn.iocoder.yudao.module.energy.convert.report.EnergyReportDataConvert;
import cn.iocoder.yudao.module.energy.dal.dataobject.report.EnergyReportDataDO;
import cn.iocoder.yudao.module.energy.enums.report.EnergyReportDataTypeEnum;
import cn.iocoder.yudao.module.energy.service.report.EnergyReportDataService;
import cn.iocoder.yudao.module.energy.util.DateProcessorHelper;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.module.energy.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;

@Tag(name = "管理后台 - 能耗报告数据")
@RestController
@RequestMapping("/energy/report")
@Validated
@Slf4j
public class EnergyReportDataController {

    @Resource
    private EnergyReportDataService reportDataService;
    
    @Resource
    private WebSocketSenderApi webSocketSenderApi;
    
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND);
    
    // 配置JSON解析器，用于处理日期类型
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
            .registerModule(new JavaTimeModule())
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    @PostMapping("/create")
    @Operation(summary = "创建能耗报告数据")
    @PreAuthorize("@ss.hasPermission('energy:report:create')")
    public CommonResult<Long> createReportData(@Valid @RequestBody EnergyReportDataCreateReqVO createReqVO) {
        // 确保日期不是1970年
        if (createReqVO.getReportDataTime() != null) {
            createReqVO.setReportDataTime(DateProcessorHelper.processDateTime(createReqVO.getReportDataTime()));
        }
        
        // 直接使用处理后的日期值
        Long reportDataId = reportDataService.createReportData(createReqVO);
        
        // 创建报告数据后，通过WebSocket发送消息通知前端
        Map<String, Object> message = new HashMap<>();
        message.put("id", reportDataId);
        message.put("deviceId", createReqVO.getDeviceId());
        message.put("reportDataType", createReqVO.getReportDataType());
        message.put("reportDataValue", createReqVO.getReportDataValue());
        
        try {
            // 获取当前登录用户信息
            Integer userType = WebFrameworkUtils.getLoginUserType();
            Long userId = SecurityFrameworkUtils.getLoginUserId();
            
            log.info("准备发送WebSocket消息: type=energy-report-created, userType={}, userId={}, content={}", 
                    userType, userId, message);

            // 方式1：发送给当前用户
            if (userType != null && userId != null) {
                webSocketSenderApi.sendObject(userType, userId, "energy-report-created", message);
                log.info("WebSocket消息已发送给指定用户: userType={}, userId={}", userType, userId);
            } else {
                log.warn("当前用户信息不完整，尝试使用其他方式发送: userType={}, userId={}", userType, userId);
            }
            
            // 方式2：广播给所有用户（作为备用方案）
            Integer adminType = 1; // 管理员类型，一般为1
            webSocketSenderApi.sendObject(adminType, "energy-report-created", message);
            log.info("WebSocket消息已广播给所有用户");
        } catch (Exception e) {
            log.error("发送WebSocket消息失败", e);
        }
        
        return success(reportDataId);
    }
    
    @PostMapping("/batch-import")
    @Operation(summary = "批量导入能耗报告数据")
    @PreAuthorize("@ss.hasPermission('energy:report:create')")
    public CommonResult<Integer> batchImportReportData(@Valid @RequestBody List<EnergyReportDataBatchImportVO> batchImportVOs) {
        // 处理每个项的日期
        for (EnergyReportDataBatchImportVO vo : batchImportVOs) {
            if (vo.getReportDataTime() != null) {
                vo.setReportDataTime(DateProcessorHelper.processDateTime(vo.getReportDataTime()));
            }
        }
        
        // 批量创建
        int successCount = reportDataService.batchCreateReportData(batchImportVOs);
        return success(successCount);
    }

    @PostMapping("/import-file")
    @Operation(summary = "从文件导入能耗报告数据")
    @PreAuthorize("@ss.hasPermission('energy:report:create')")
    public CommonResult<Integer> importReportDataFromFile(@RequestParam("file") MultipartFile file) {
        if (file == null || file.isEmpty()) {
            return success(0);
        }
        
        try {
            // 读取文件内容
            byte[] bytes = file.getBytes();
            String content = new String(bytes, StandardCharsets.UTF_8);
            
            // 将JSON字符串转换为对象列表
            List<EnergyReportDataBatchImportVO> batchImportVOs = OBJECT_MAPPER.readValue(
                content, 
                OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, EnergyReportDataBatchImportVO.class)
            );
            
            // 处理日期
            for (EnergyReportDataBatchImportVO vo : batchImportVOs) {
                if (vo.getReportDataTime() != null) {
                    vo.setReportDataTime(DateProcessorHelper.processDateTime(vo.getReportDataTime()));
                }
            }
            
            // 批量创建
            int successCount = reportDataService.batchCreateReportData(batchImportVOs);
            return success(successCount);
        } catch (Exception e) {
            e.printStackTrace();
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.REPORT_DATA_IMPORT_ERROR, e.getMessage());
        }
    }
    
    @PostMapping("/test-date")
    @Operation(summary = "测试日期格式解析")
    public CommonResult<Map<String, Object>> testDateFormat(@RequestBody Map<String, String> params) {
        String dateStr = params.get("reportDataTime");
        
        Map<String, Object> result = new HashMap<>();
        result.put("originalDateString", dateStr);
        
        try {
            // 尝试解析日期
            LocalDateTime dateTime = DateProcessorHelper.processDateString(dateStr);
            result.put("parsedDate", dateTime);
            result.put("formattedDate", dateTime.format(DATE_TIME_FORMATTER));
            result.put("year", dateTime.getYear());
            result.put("success", true);
        } catch (Exception e) {
            result.put("error", e.getMessage());
            result.put("success", false);
        }
        
        return success(result);
    }

    @PutMapping("/update")
    @Operation(summary = "更新能耗报告数据")
    @PreAuthorize("@ss.hasPermission('energy:report:update')")
    public CommonResult<Boolean> updateReportData(@Valid @RequestBody EnergyReportDataUpdateReqVO updateReqVO) {
        // 确保日期不是1970年
        if (updateReqVO.getReportDataTime() != null) {
            updateReqVO.setReportDataTime(DateProcessorHelper.processDateTime(updateReqVO.getReportDataTime()));
        }
        
        // 直接使用处理后的日期值
        reportDataService.updateReportData(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除能耗报告数据")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('energy:report:delete')")
    public CommonResult<Boolean> deleteReportData(@RequestParam("id") Long id) {
        reportDataService.deleteReportData(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得能耗报告数据")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('energy:report:query')")
    public CommonResult<EnergyReportDataRespVO> getReportData(@RequestParam("id") Long id) {
        EnergyReportDataDO reportData = reportDataService.getReportData(id);
        return success(EnergyReportDataConvert.INSTANCE.convert(reportData));
    }

    @GetMapping("/page")
    @Operation(summary = "获得能耗报告数据分页")
    @PreAuthorize("@ss.hasPermission('energy:report:query')")
    public CommonResult<PageResult<EnergyReportDataRespVO>> getReportDataPage(@Valid EnergyReportDataPageReqVO pageVO) {
        PageResult<EnergyReportDataDO> pageResult = reportDataService.getReportDataPage(pageVO);
        return success(EnergyReportDataConvert.INSTANCE.convertPage(pageResult));
    }
    
    @GetMapping("/export")
    @Operation(summary = "导出能耗报告数据")
    @PreAuthorize("@ss.hasPermission('energy:report:export')")
    public void exportReportData(@Valid EnergyReportDataPageReqVO pageVO, HttpServletResponse response) throws IOException {
        // 查询数据
        List<EnergyReportDataDO> list = reportDataService.getReportDataList(pageVO);
        
        // 转换为导出格式
        List<EnergyReportDataExportVO> exportList = EnergyReportDataConvert.INSTANCE.convertList02(list);
        
        // 导出Excel
        ExcelUtils.write(response, "能耗报告数据.xlsx", "数据", EnergyReportDataExportVO.class, exportList);
    }
} 